package de.mmis.core.base.abstracttree.serializer.selector;

import java.util.Map;

import de.mmis.core.base.abstracttree.InnerNode;
import de.mmis.core.base.abstracttree.Tree;
import de.mmis.core.base.abstracttree.serializer.DeserializableException;
import de.mmis.core.base.abstracttree.serializer.Serializable;
import de.mmis.core.base.abstracttree.serializer.SerializerHelper;
import de.mmis.core.base.gclass.GClass;
import de.mmis.core.base.gclass.GParameterized;

/**
 * {@link InstanceSelector} representing an {@link Serializable} object type.
 * The target type determines the class that is uses for deserialization)
 * 
 * @author Christian Koch
 */
public class SerializableSelector extends InstanceSelector {

	private final Tree[] exps;
	private final ClassLoader classLoader;

	public SerializableSelector(Tree[] exps, ClassLoader classLoader,
			String id, Map<String, Object> idmap) {
		super(id, idmap);

		this.exps = exps;
		this.classLoader = classLoader;
	}

	@Override
	public Object createInstance(GClass gclass)
			throws InstanceSelectorException {

		if (gclass instanceof GParameterized)
			try {
				return SerializerHelper.deserializeWithClass(
						gclass.getBaseClass(), this.exps, this.classLoader, getID(),
						getIDMap()).createInstance(gclass);
			} catch (DeserializableException e) {
				throw new InstanceSelectorException(
						"cannot convert serializable " + new InnerNode(this.exps)
								+ " to type \"" + gclass + "\"", e);
			}

		throw new InstanceSelectorException("cannot convert serializable "
				+ this.exps + " to type \"" + gclass + "\"");
	}

}
